package com.sso.oauth2.server.config.auath2;

import com.sso.oauth2.server.config.auath2.impl.CustomClientDetailsImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

import static com.sso.oauth2.server.constant.GrantTypes.*;

/**
 * OAuth 2.0 Server 相关配置
 *
 * @author yins
 * @date 2021/07/13 11:06
 **/
@Configuration
@EnableAuthorizationServer
public class OauthServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AuthenticationManager authenticationManager;

/*@Autowired
  private CustomClientDetailsImpl customClientDetails; */

    /**
     * a configurer that defines the client details service. Client details can be initialized, or you can just refer to an existing store.
     * 定义客户端详细信息服务的配置器。可以初始化客户端详细信息，也可以仅参考现有商店。
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient("duia_client")
                .secret(passwordEncoder.encode("duia2018"))
                // 单独演示 开启此配置
                .redirectUris("https://duia.com/")
                // 配合项目 client时 使用
//                .redirectUris("http://localhost:21000/login")
                .scopes("all")
                // 是否自动授权
                .autoApprove(true)
                // token 有效时间 单位：秒
                .accessTokenValiditySeconds(2000)
                // refresh token 有效时间 单位：秒
//                .refreshTokenValiditySeconds(70)
                // 支持的认证模式
                .authorizedGrantTypes(
                        AUTHORIZATION_CODE.type
                        , PASSWORD.type
                        , IMPLICIT.type
                        , CLIENT.type
                        , REFRESH_TOKEN.type
                )
        // 使用自定义客户端时 配套
//                .withClientDetails(clientDetailsService)
        ;

    }

    /**
     * defines the security constraints on the token endpoint.
     * 定义令牌端点上的安全约束。
     *
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated() || permitAll() ")
//                .authenticationEntryPoint() 自定义一场处理端口
//                .sslOnly()
//                .accessDeniedHandler() 自定义无权限访问
                .allowFormAuthenticationForClients()
        ;
    }

    /**
     * defines the authorization and token endpoints and the token services.
     * 定义授权和令牌端点以及令牌服务
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                // 配置自定义 用户
                .userDetailsService(userDetailsService)
                // 支持password授权方式时 必配
                .authenticationManager(authenticationManager)
        ;
    }

}
